﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Transactions;
using MediaBrowser.Entities;
using MediaBrowser.IRepository;
using MediaBrowser.IServices;
using System.Threading;

namespace MediaBrowser.Services
{
    /// <summary>
    /// Classe Service Media
    /// </summary>
    public class MediaManager : IMediaManager
    {
        private IMediaRepository mediaRepository;

        public MediaManager(IMediaRepository mediaRepository)
        {
            this.mediaRepository = mediaRepository;
        }

        /// <summary>
        /// Retourne la Liste des média
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Media> ListMediasByCategory(int idCategory)
        {
            return mediaRepository.ListMediasByCategory(idCategory);
        }

        /// <summary>
        /// Modification d'un média
        /// </summary>
        /// <param name="media"></param>
        /// <returns></returns>
        public bool UpdateMedia(Media media)
        {
            if ((media == null) || (media.Id <= 0))
            {
                throw new ArgumentNullException("Media null Exception");
            }
            return mediaRepository.UpdateMedia(media);
        }

        #region PICTURES

        /// <summary>
        /// Création d'une Image
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public Media CreatePicture(string fileName)
        {
            Media m = null;
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    File.Copy(fileName, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Data/Images/" + Path.GetFileName(fileName));
                    int idMax = mediaRepository.CountMedia();
                    m = new Media(idMax + 1, Path.GetFileName(fileName), DateTime.Now, "", new Category(3, "", DateTime.Now, ""),
                                        @"Data\Images\" + Path.GetFileName(fileName), "");
                    mediaRepository.CreateMedia(m);
                    m.UrlImage = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), m.UrlImage);
                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }
            return m;
        }

        /// <summary>
        /// Suppresion d'une Image
        /// </summary>
        /// <param name="m"></param>
        public void DeletePicture(Media m)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    File.Delete(m.UrlImage);
                    mediaRepository.DeleteMedia(m);
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }
        }

        #endregion

        #region MOVIES

        /// <summary>
        /// Sauvegarder un Film
        /// </summary>
        /// <param name="newMedia"></param>
        /// <param name="previousMedia"></param>
        public Media SaveMovie(Media newMedia, Media previousMedia)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    Media returnMedia = null;

                    #region Ajout
                    if (newMedia.Id == 0)
                    {
                        String urlImage = String.Empty;
                        String urlContent = String.Empty;
                        if (!String.IsNullOrEmpty(newMedia.UrlImage))
                        {
                            if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Images\" + Path.GetFileName(newMedia.UrlImage)))
                            {
                                File.Copy(newMedia.UrlImage, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Images\" + Path.GetFileName(newMedia.UrlImage), true);
                            }
                            urlImage = @"Data\Images\" + Path.GetFileName(newMedia.UrlImage);
                        }

                        if (!String.IsNullOrEmpty(newMedia.UrlContent))
                        {
                            if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Movies\" + Path.GetFileName(newMedia.UrlContent)))
                            {
                                File.Copy(newMedia.UrlContent, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Movies\" + Path.GetFileName(newMedia.UrlContent), true);
                            }
                            urlContent = @"Data\Movies\" + Path.GetFileName(newMedia.UrlContent);
                        }

                        int idMax = mediaRepository.CountMedia();
                        Media m = new Media(idMax + 1, newMedia.Name, DateTime.Now, newMedia.Description, new Category(1, "", DateTime.Now, ""),
                                            urlImage, urlContent);
                        mediaRepository.CreateMedia(m);
                        if (!String.IsNullOrEmpty(urlImage))
                        {
                            m.UrlImage = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), m.UrlImage);
                        }
                        if (!String.IsNullOrEmpty(urlContent))
                        {
                            m.UrlContent = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), m.UrlContent);
                        }

                        returnMedia = m;
                    }
                    #endregion

                    #region Modification
                    else
                    {
                        if (newMedia.UrlImage != previousMedia.UrlImage)
                        {
                            if (File.Exists(previousMedia.UrlImage)) { File.Delete(previousMedia.UrlImage); }
                            if (!String.IsNullOrEmpty(newMedia.UrlImage))
                            {
                                if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Images\" + Path.GetFileName(newMedia.UrlImage)))
                                {
                                    File.Copy(newMedia.UrlImage, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Images\" + Path.GetFileName(newMedia.UrlImage), true);
                                }
                                newMedia.UrlImage = @"Data\Images\" + Path.GetFileName(newMedia.UrlImage);
                            }
                            else
                            {
                                newMedia.UrlImage = String.Empty;
                            }
                        }

                        if (newMedia.UrlContent != previousMedia.UrlContent)
                        {
                            if (File.Exists(previousMedia.UrlContent)) { File.Delete(previousMedia.UrlContent); }
                            if (!String.IsNullOrEmpty(newMedia.UrlContent))
                            {
                                if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Movies\" + Path.GetFileName(newMedia.UrlContent)))
                                {
                                    File.Copy(newMedia.UrlContent, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Movies\" + Path.GetFileName(newMedia.UrlContent), true);
                                }
                                newMedia.UrlContent = @"Data\Movies\" + Path.GetFileName(newMedia.UrlContent);
                            }
                            else
                            {
                                newMedia.UrlContent = String.Empty;
                            }
                        }

                        mediaRepository.UpdateMedia(newMedia);

                        if (!String.IsNullOrEmpty(newMedia.UrlImage))
                        {
                            newMedia.UrlImage = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), newMedia.UrlImage);
                        }

                        if (!String.IsNullOrEmpty(newMedia.UrlContent))
                        {
                            newMedia.UrlContent = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), newMedia.UrlContent);
                        }
                        returnMedia = newMedia;

                    }
                    #endregion

                    scope.Complete();

                    return returnMedia;
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }
        }

        /// <summary>
        /// Suppression d'un Film
        /// </summary>
        /// <param name="m"></param>
        public void DeleteMovie(Media m)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    if (File.Exists(m.UrlContent)) { File.Delete(m.UrlContent); }
                    if (File.Exists(m.UrlImage)) { File.Delete(m.UrlImage); }
                    mediaRepository.DeleteMedia(m);
                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }
        }

        #endregion

        #region BOOK

        /// <summary>
        /// Sauvegarder un Livre
        /// </summary>
        /// <param name="newMedia"></param>
        /// <param name="previousMedia"></param>
        public Media SaveBook(Media newMedia, Media previousMedia)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    Media returnMedia = null;

                    #region Ajout
                    if (newMedia.Id == 0)
                    {
                        String urlContent = String.Empty;

                        if (!String.IsNullOrEmpty(newMedia.UrlContent))
                        {
                            if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Books\" + Path.GetFileName(newMedia.UrlContent)))
                            {
                                File.Copy(newMedia.UrlContent, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Books\" + Path.GetFileName(newMedia.UrlContent), true);
                            }
                            urlContent = @"Data\Books\" + Path.GetFileName(newMedia.UrlContent);
                        }

                        int idMax = mediaRepository.CountMedia();
                        Media m = new Media(idMax + 1, newMedia.Name, DateTime.Now, newMedia.Description, new Category(4, "", DateTime.Now, ""),
                                            String.Empty, urlContent);
                        mediaRepository.CreateMedia(m);

                        if (!String.IsNullOrEmpty(urlContent))
                        {
                            m.UrlContent = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), m.UrlContent);
                        }

                        returnMedia = m;
                    }
                    #endregion

                    #region Modification
                    else
                    {
                        if (newMedia.UrlContent != previousMedia.UrlContent)
                        {
                            if (File.Exists(previousMedia.UrlContent)) { File.Delete(previousMedia.UrlContent); }
                            if (!String.IsNullOrEmpty(newMedia.UrlContent))
                            {
                                if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Books\" + Path.GetFileName(newMedia.UrlContent)))
                                {
                                    File.Copy(newMedia.UrlContent, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Books\" + Path.GetFileName(newMedia.UrlContent), true);
                                }
                                newMedia.UrlContent = @"Data\Books\" + Path.GetFileName(newMedia.UrlContent);
                            }
                            else
                            {
                                newMedia.UrlContent = String.Empty;
                            }
                        }

                        mediaRepository.UpdateMedia(newMedia);

                        if (!String.IsNullOrEmpty(newMedia.UrlContent))
                        {
                            newMedia.UrlContent = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), newMedia.UrlContent);
                        }
                        returnMedia = newMedia;

                    }
                    #endregion

                    scope.Complete();

                    return returnMedia;
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }
        }

        /// <summary>
        /// Suppression d'un Livre
        /// </summary>
        /// <param name="m"></param>
        public void DeleteBook(Media m)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    if (File.Exists(m.UrlContent)) { File.Delete(m.UrlContent); }
                    mediaRepository.DeleteMedia(m);
                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }
        }

        #endregion

        #region ALBUM/MUSIC

        /// <summary>
        /// Sauvegarder un album
        /// </summary>
        /// <param name="newMedia"></param>
        /// <param name="oldMedia"></param>
        public Media SaveAlbum(Media newMedia, Media previousMedia)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    Media returnMedia = null;

                    #region Ajout

                    if (newMedia.Id == 0)
                    {
                        String urlImage = String.Empty;
                        if (!String.IsNullOrEmpty(newMedia.UrlImage))
                        {
                            if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Images\" + Path.GetFileName(newMedia.UrlImage)))
                            {
                                File.Copy(newMedia.UrlImage, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Images\" + Path.GetFileName(newMedia.UrlImage), true);
                            }
                            urlImage = @"Data\Images\" + Path.GetFileName(newMedia.UrlImage);
                        }

                        int idMax = mediaRepository.CountMedia();
                        Media m = new Media(idMax + 1, newMedia.Name, DateTime.Now, String.Empty, new Category(2, "", DateTime.Now, ""),
                                            urlImage, String.Empty);
                        mediaRepository.CreateMedia(m);
                        if (!String.IsNullOrEmpty(urlImage))
                        {
                            m.UrlImage = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), m.UrlImage);
                        }

                        returnMedia = m;
                    }

                    #endregion

                    #region Modification

                    else
                    {
                        if (newMedia.UrlImage != previousMedia.UrlImage)
                        {
                            if (File.Exists(previousMedia.UrlImage)) { File.Delete(previousMedia.UrlImage); }
                            if (!String.IsNullOrEmpty(newMedia.UrlImage))
                            {
                                if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Images\" + Path.GetFileName(newMedia.UrlImage)))
                                {
                                    File.Copy(newMedia.UrlImage, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Images\" + Path.GetFileName(newMedia.UrlImage), true);
                                }
                                newMedia.UrlImage = @"Data\Images\" + Path.GetFileName(newMedia.UrlImage);
                            }
                            else
                            {
                                newMedia.UrlImage = String.Empty;
                            }
                        }

                        mediaRepository.UpdateMedia(newMedia);

                        if (!String.IsNullOrEmpty(newMedia.UrlImage))
                        {
                            newMedia.UrlImage = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), newMedia.UrlImage);
                        }

                        returnMedia = newMedia;
                    }

                    #endregion

                    scope.Complete();

                    return returnMedia;
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }
        }

        /// <summary>
        /// Suppression d'un album
        /// </summary>
        /// <param name="m"></param>
        public void DeleteAlbum(Media m)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    foreach (MediaItem mediaItem in m.MediaItems)
                    {
                        if (File.Exists(mediaItem.UrlContent)) { File.Delete(mediaItem.UrlContent); }
                    }
                    if (File.Exists(m.UrlImage)) { File.Delete(m.UrlImage); }
                    mediaRepository.DeleteMedia(m);
                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }
        }

        /// <summary>
        /// Création d'une nouvelle Musique
        /// </summary>
        /// <param name="idMedia"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public MediaItem CreateMusic(int idMedia, string fileName)
        {
            MediaItem m = null;
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    String urlContent = string.Empty;
                    if (!String.IsNullOrEmpty(fileName))
                    {
                        if (!File.Exists(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Musics\" + Path.GetFileName(fileName)))
                        {
                            File.Copy(fileName, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Musics\" + Path.GetFileName(fileName), true);
                        }
                        urlContent = @"Data\Musics\" + Path.GetFileName(fileName);
                    }
                    int idMax = mediaRepository.CountMediaItem(idMedia);
                    m = new MediaItem(idMax + 1, Path.GetFileNameWithoutExtension(fileName), DateTime.Now, String.Empty, urlContent);

                    //Save MediaItem
                    mediaRepository.CreateMediaItem(idMedia, m);

                    m.UrlContent = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\Data\Musics\" + Path.GetFileName(fileName);
                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }

            return m;
        }

        /// <summary>
        /// Suppression d'une Musique
        /// </summary>
        /// <param name="idMedia"></param>
        /// <param name="m"></param>
        public void DeleteMusic(int idMedia, MediaItem m)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    if (File.Exists(m.UrlContent)) { File.Delete(m.UrlContent); }
                    mediaRepository.DeleteMediaItem(idMedia, m);
                    scope.Complete();
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message, ex.InnerException);
                }
            }

        }

        #endregion
    }
}
